From: cl349@freefall.cl.cam.ac.uk Date: Mon, 4 Oct 2004 14:55:47 +0000 (+0000) Subject: bitkeeper revision 1.1159.99.3 (41616473OrT0a62n0DQje0P8dGOxwA) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~17400^2~549^2 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22?a=commitdiff_plain;h=83bc72283c787f7f5017f60d3ec4f840cf2ff5cc;p=xen.git bitkeeper revision 1.1159.99.3 (41616473OrT0a62n0DQje0P8dGOxwA) Go back to writable pagetables v1: - disconnect pagetable page mapped va space - give guest write permissions to its pagetable page - tlb flush to avoid intermediate caching - reorder operations for correctness on smp --- diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index baf8a040ff..206cb2a3fc 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1642,56 +1642,60 @@ void ptwr_flush(const int which) { unsigned long pte, *ptep; l1_pgentry_t *pl1e; + l2_pgentry_t *pl2e, nl2e; int cpu = smp_processor_id(); int i; ptep = (unsigned long *)&linear_pg_table [ptwr_info[cpu].ptinfo[which].l1va>>PAGE_SHIFT]; + /* make pt page write protected */ + if ( unlikely(__get_user(pte, ptep)) ) { + MEM_LOG("ptwr: Could not read pte at %p\n", ptep); + domain_crash(); + } + PTWR_PRINTK(PP_ALL, ("disconnected_l1va at %p is %08lx\n", + ptep, pte)); + pte &= ~_PAGE_RW; + if ( unlikely(__put_user(pte, ptep)) ) { + MEM_LOG("ptwr: Could not update pte at %p\n", ptep); + domain_crash(); + } + __flush_tlb_one(ptwr_info[cpu].ptinfo[which].l1va); + PTWR_PRINTK(PP_ALL, ("disconnected_l1va at %p now %08lx\n", + ptep, pte)); + pl1e = ptwr_info[cpu].ptinfo[which].pl1e; for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) { l1_pgentry_t ol1e, nl1e; - nl1e = ptwr_info[cpu].ptinfo[which].page[i]; - ol1e = pl1e[i]; + ol1e = ptwr_info[cpu].ptinfo[which].page[i]; + nl1e = pl1e[i]; if (likely(l1_pgentry_val(ol1e) == l1_pgentry_val(nl1e))) continue; - if (likely(l1_pgentry_val(ol1e) == (l1_pgentry_val(nl1e) | _PAGE_RW))) - { - if (likely(readonly_page_from_l1e(nl1e))) { - pl1e[i] = nl1e; - continue; - } - } + if (likely(l1_pgentry_val(ol1e) == (l1_pgentry_val(nl1e) | _PAGE_RW)) + && readonly_page_from_l1e(nl1e)) + continue; if (unlikely(l1_pgentry_val(ol1e) & _PAGE_PRESENT)) put_page_from_l1e(ol1e, current); if (unlikely(!get_page_from_l1e(nl1e, current))) { MEM_LOG("ptwr: Could not re-validate l1 page\n"); domain_crash(); } - pl1e[i] = nl1e; } unmap_domain_mem(pl1e); - /* make pt page write protected */ - if ( unlikely(__get_user(pte, ptep)) ) { - MEM_LOG("ptwr: Could not read pte at %p\n", ptep); - domain_crash(); - } - PTWR_PRINTK(PP_ALL, ("disconnected_l1va at %p is %08lx\n", - ptep, pte)); - pte = (ptwr_info[cpu].ptinfo[which].pte & PAGE_MASK) | - (pte & ~(PAGE_MASK|_PAGE_RW)); - if ( unlikely(__put_user(pte, ptep)) ) { - MEM_LOG("ptwr: Could not update pte at %p\n", ptep); - domain_crash(); + if (which == PTWR_PT_ACTIVE) { + /* reconnect l1 page */ + pl2e = &linear_l2_table[ptwr_info[cpu].active_pteidx]; + nl2e = mk_l2_pgentry(l2_pgentry_val(*pl2e) | _PAGE_PRESENT); + update_l2e(pl2e, *pl2e, nl2e); } if ( unlikely(current->mm.shadow_mode) ) { unsigned long spte; unsigned long sstat = - get_shadow_status(¤t->mm, - ptwr_info[cpu].ptinfo[which].pte >> PAGE_SHIFT); + get_shadow_status(¤t->mm, pte >> PAGE_SHIFT); if ( sstat & PSH_shadowed ) { @@ -1715,10 +1719,6 @@ void ptwr_flush(const int which) [ptwr_info[cpu].ptinfo[which].l1va>>PAGE_SHIFT]); } - __flush_tlb_one(ptwr_info[cpu].ptinfo[which].l1va); - PTWR_PRINTK(PP_ALL, ("disconnected_l1va at %p now %08lx\n", - ptep, pte)); - ptwr_info[cpu].ptinfo[which].l1va = 0; } @@ -1727,7 +1727,7 @@ int ptwr_do_page_fault(unsigned long addr) /* write page fault, check if we're trying to modify an l1 page table */ unsigned long pte, pfn; struct pfn_info *page; - l2_pgentry_t *pl2e; + l2_pgentry_t *pl2e, nl2e; int cpu = smp_processor_id(); int which; @@ -1771,8 +1771,13 @@ int ptwr_do_page_fault(unsigned long addr) ptwr_flush(which); ptwr_info[cpu].ptinfo[which].l1va = addr | 1; - if (which == PTWR_PT_ACTIVE) + if (which == PTWR_PT_ACTIVE) { ptwr_info[cpu].active_pteidx = va_mask; + /* disconnect l1 page */ + nl2e = mk_l2_pgentry((l2_pgentry_val(*pl2e) & ~_PAGE_PRESENT)); + update_l2e(pl2e, *pl2e, nl2e); + flush_tlb(); + } ptwr_info[cpu].ptinfo[which].pl1e = map_domain_mem(pfn << PAGE_SHIFT); @@ -1781,10 +1786,7 @@ int ptwr_do_page_fault(unsigned long addr) ENTRIES_PER_L1_PAGETABLE * sizeof(l1_pgentry_t)); /* make pt page writable */ - ptwr_info[cpu].ptinfo[which].pte = pte; - pte = (virt_to_phys(ptwr_info[cpu].ptinfo[which].page) & - PAGE_MASK) | _PAGE_RW | (pte & ~PAGE_MASK); - + pte |= _PAGE_RW; PTWR_PRINTK(PP_ALL, ("update %p pte to %08lx\n", &linear_pg_table[addr>>PAGE_SHIFT], pte)); if ( unlikely(__put_user(pte, (unsigned long *) diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index cd565d8dcc..c8e0e16953 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -254,7 +254,6 @@ extern vm_assist_info_t vm_assist_info[]; typedef struct { unsigned long l1va; l1_pgentry_t *page; - unsigned long pte; l1_pgentry_t *pl1e; } ptwr_ptinfo_t;